﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Linq;
using FinPlusCommon;
using System.ComponentModel;
using log = Logger.Logger;

namespace FinPlusComponents
{
    public class FinPlusQuoteConnection: FinPlusComponent
    {
        private enum Params { QuoteSource, ReceiveAction, PublishAction, Size, FunctionName }
        private FinPlusMessaging _quotesMessaging;
        private IFinPlusComp _quoteAdaptorConn;
        private IFunction _quoteAdaptor;
        private readonly string _sourceName;
        private const int _quoteExecutePublishPercent = 5, _quoteExecutePercent = 90;

        //construct
        public FinPlusQuoteConnection(string name, IFinPlusComp quoteAdaptors, IFinPlusComp quotesMessaging) 
        {
            _sourceName = name;
            _quoteAdaptorConn = quoteAdaptors;
            _quoteAdaptor = quoteAdaptors.Adaptor.Values.Where(f => f[Params.QuoteSource.ToString()].ToString().Equals(_sourceName)).First<IFunction>();
            _quoteAdaptor.Get(Params.PublishAction.ToString(), Publish_Update);
            _quotesMessaging = (FinPlusMessaging)quotesMessaging;
            _quotesMessaging.OnUpdate += Message_Update;
            IsValid = true;
        }

        //common control interface
        public override void CmdExecute(IFunction command)
        {
            try
            {
                CmdCapture(command);

                switch ((Cmds)Enum.Parse(typeof(Cmds), command.Name, true))
                {
                    case Cmds.Quote: Quote(command); break;
                    case Cmds.QuoteCancel: QuoteCancel(command); break;
                    case Cmds.QuoteExecute: QuoteExecute(command); break;
                    case Cmds.QuoteAccept: QuoteAccept(command); break;
                    case Cmds.QuoteDecline: QuoteDecline(command); break;
                    case Cmds.QuotePublish: QuotePublish(command); break;
                    case Cmds.QuoteExecutePublish: QuoteExecutePublish(command); break;
                    case Cmds.QuoteCancelPublish: QuoteCancelPublish(command); break;
                    case Cmds.QuoteDeclinePublish: QuoteDeclinePublish(command); break;
                    case Cmds.QuoteAcceptPublish: QuoteAcceptPublish(command); break;
                    default: throw new Exception(string.Format("event not recognised {0}", command.Name));
                }
            }
            catch (CmdExecuteException e)
            {
                IsValid = log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        public override void Dispose()
        {
            try
            {
                if (_quoteAdaptorConn != null)
                    _quoteAdaptorConn.Dispose();
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Warning, e.Message, e);
            }
        }

        //quote
        private bool Quote(IFunction func)
        {
            //vendor quote
            _quoteAdaptor.Get(Params.ReceiveAction.ToString()).Set(func);
            return true;
        }

        private bool QuoteCancel(IFunction func)
        {
            //vendor cancels
            _quoteAdaptor.Get(Params.ReceiveAction.ToString()).Set(func);
            return true;
        }

        private bool QuoteExecute(IFunction func)
        {
            //trader trys to execute 
            if (new Random().Next(0, 100) < _quoteExecutePercent)
            {
                //route as accept
                func.Get(Params.FunctionName.ToString()).Value = func.Name = Cmds.QuoteAccept.ToString();
                Message_Update(this, func);
            }
            else
            {
                //route as decline
                func.Get(Params.FunctionName.ToString()).Value = func.Name = Cmds.QuoteDecline.ToString();
                Message_Update(this, func);
            }
            return true;
        }

        private bool QuoteAccept(IFunction func)
        {
            _quoteAdaptor.Get(Params.ReceiveAction.ToString()).Set(func);
            return true;
        }

        private bool QuoteDecline(IFunction func)
        {
            _quoteAdaptor.Get(Params.ReceiveAction.ToString()).Set(func);
            return true;
        }

        private bool QuotePublish(IFunction func)
        {
            if ((double)func.Value(Params.Size.ToString()) != 0 && new Random().Next(0, 100) < _quoteExecutePublishPercent)
            {
                func.Get(Params.FunctionName.ToString()).Value = func.Name = Cmds.QuoteExecutePublish.ToString();
                Message_Update(this, func);
            }

            return true;
        }

        private bool QuoteCancelPublish(IFunction func)
        {
            //TODO
            return true;
        }

        private bool QuoteAcceptPublish(IFunction func)
        {
            //TODO
            return true;
        }

        private bool QuoteDeclinePublish(IFunction func)
        {
            //TODO
            return true;
        }

        private bool QuoteExecutePublish(IFunction func)
        {
            _quoteAdaptor.Get(Params.ReceiveAction.ToString()).Set(func);
            return true;
        }

        //cmds
        private enum Cmds { Quote, QuoteCancel, QuoteExecute, QuoteAccept, QuoteDecline, QuotePublish, QuoteDeclinePublish, QuoteCancelPublish, QuoteAcceptPublish, QuoteExecutePublish };

        //events
        private void Message_Update(object s, IFunction func) { CmdExecute(func); }
        private void Publish_Update(object s, PropertyChangedEventArgs a) { CmdRouter(s); }
    }
}
